using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;

namespace WindowsControl
{
	/// <summary>
	/// Summary description for UserControl1.
	/// </summary>

	public class MouseForm : System.Windows.Forms.Form
	{
		/// <summary>
		/// Required designer variable.
		/// </summary>

		public int formIndex = 0;
		private delegate Point MouseMoveHandler();
		private MouseMoveHandler UpdateTargetPosition;
		private IRange xRange = new RangeLimit();
		private IRange yRange = new RangeLimit();
		private System.ComponentModel.Container components = null;
		private Size formSize = new Size(200,200);
		private float formScale = 1;
		public Point Offset = new Point(0,0);
		private Point crossOffset = new Point(0,0);
		private Point oldCrossPostion = new Point(0,0);
		private FloatPoint oldPos = new FloatPoint(0,0);
		private FloatPoint pos = new FloatPoint(0,0);
		private bool mouseCancel = false;
		public Point TargetCenter = new Point(15,14);
		public System.Windows.Forms.Label Target;
		public void NewLocation( Point p)
		{
			p.X += this.Offset.X;
			p.Y += this.Offset.Y;
			this.Location = p;
		}
		public void SetTargetBackgroundColor(int a, int r, int g, int b)
		{
			Target.BackColor = Color.FromArgb(r,g,b);
		}
		public void SetTargetBackgroundColor(int r, int g, int b)
		{
			SetTargetBackgroundColor(255,r,g,b);
		}
		public bool SetTargetImage(string filePath)
		{
			try
			{
				Target.Image = Image.FromFile(filePath);
				Target.Text = "";
				this.ResetTargetCenter();
				return true;
			}
			catch
			{
				return false;
			}
		}
		public void ScaleSize(float s)
		{
			formScale = s;
			int x = (int)(this.formSize.Width * formScale);
			int y = (int)(this.formSize.Height * formScale);
			if (x<20) x = 20;
			if (y<20) y = 20;
			this.Size = new Size(x,y);
			SetPos(pos.x,pos.y);
			//x = (int)(this.Offset.X * s);
			//y = this.Offset.Y;
			//this.Offset = new Point(x,y);
		}
		public void SetSize(int x,int y)
		{
			formScale = 1;
			FloatPoint p = GetPos();
			this.formSize = new Size(x,y);
			x = (int)(x * formScale);
			y = (int)(y * formScale);
			this.Size = new Size(x,y);
			SetPos(p.x,p.y);
		}
		public void ResetTargetCenter()
		{
			TargetCenter.X = Target.Size.Width/2;
			TargetCenter.Y = Target.Size.Height/2;
		}
		public void SetTargetSize(int x,int y)
		{
			Size s = new Size(x,y);
			Target.Size = s;
			this.ResetTargetCenter();
		}
		private void SetOldCrossPostion()
		{
			this.oldCrossPostion = this.Target.Location;
		}
		public void SetRange(float xMin,float yMin,float xMax,float yMax)
		{
			//xRange.set(xMin, xMax);
			//yRange.set(yMin, yMax);
			if (xMin == xMax)
			{
				UpdateTargetPosition = new MouseMoveHandler(MoveY);
				xRange = new DummyRangeLimit(xMax);
				yRange = new RangeLimit(yMin, yMax);
			}
			else
			{
				if (yMin == yMax)
				{
					UpdateTargetPosition = new MouseMoveHandler(MoveX);
					xRange = new RangeLimit(xMin, xMax);
					yRange = new DummyRangeLimit(yMax);
				}
				else
				{
					UpdateTargetPosition = new MouseMoveHandler(Move2d);
					xRange = new RangeLimit(xMin, xMax);
					yRange = new RangeLimit(yMin, yMax);
				}
			}
		}
		public void SetPos(float x, float y)
		{
			pos.x = xRange.clamp(x);
			pos.y = yRange.clamp(y);
			Point P = new Point(0,0);
			P.X = xRange.ScaleToWindow(pos.x,this.Size.Width)- TargetCenter.X;
			P.Y = this.Size.Height - yRange.ScaleToWindow(pos.y,this.Size.Height)- TargetCenter.Y;
			this.Target.Location = P;
			this.SetOldCrossPostion();
		}
		public FloatPoint GetPos()
		{
			setPosFromWindow();
			return pos;
		}
		private void CalcCrossOffset()
		{
			crossOffset.X = this.PointToClient(Control.MousePosition).X - this.Target.Location.X;
			crossOffset.Y = this.PointToClient(Control.MousePosition).Y - this.Target.Location.Y;
		}
		private void setPosFromWindow()
		{
			pos.x = xRange.ScaleFromWindow(this.Target.Location.X + TargetCenter.X,this.Size.Width);
			pos.y = yRange.ScaleFromWindow(this.Size.Height - (this.Target.Location.Y + TargetCenter.Y),this.Size.Height);
		}

		private Point MoveX()
		{
			Point P = this.PointToClient(Control.MousePosition);
			P.X = RangeLimit.clamp((P.X - crossOffset.X),- TargetCenter.X,this.Size.Width - TargetCenter.X);
			P.Y = (int)(this.Size.Height * 0.5) - TargetCenter.Y;
			return(P);
		}
		private Point MoveY()
		{
			Point P = this.PointToClient(Control.MousePosition);
			P.X = (int)(this.Size.Width * 0.5) - TargetCenter.X;
			P.Y = RangeLimit.clamp((P.Y - crossOffset.Y),- TargetCenter.Y,this.Size.Height - TargetCenter.Y);
			return(P);
		}
		private Point Move2d()
		{
			Point P = this.PointToClient(Control.MousePosition);
			P.X = RangeLimit.clamp((P.X - crossOffset.X),- TargetCenter.X,this.Size.Width - TargetCenter.X);
			P.Y = RangeLimit.clamp((P.Y - crossOffset.Y),- TargetCenter.Y,this.Size.Height - TargetCenter.Y);
			return(P);
		}
		private void MoveCross()
		{
			this.Target.Location = UpdateTargetPosition();
			this.setPosFromWindow();
		}	
		public event PosEventHandler PosEvent;

		public PosEventArgs GetPosEventArgs()
		{
			return new PosEventArgs(this.pos,formIndex);
		}
		protected virtual void OnPosEvent(PosEventArgs e) 
		{
			if (PosEvent != null)
				PosEvent(this, e);
		}
		private void MoveMousePos(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if ((e.Button == MouseButtons.Left) && !mouseCancel)
			{
				MoveCross();		
				OnPosEvent(GetPosEventArgs());
			}
		}
		private void SetZero(object sender, System.EventArgs e)
		{
			SetPos(0,0);
			OnPosEvent(GetPosEventArgs());
		}
		private void SetOffset(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if ((e.Button == MouseButtons.Right) && !mouseCancel)
			{
				this.Target.Location = this.oldCrossPostion;
				this.setPosFromWindow();
				mouseCancel = true;
				OnPosEvent(GetPosEventArgs());
			}
			if (e.Button == MouseButtons.Left)
			{
				mouseCancel = false;
				this.SetOldCrossPostion();
				CalcCrossOffset();
			}
		}
		public MouseForm()
		{
			// This call is required by the Windows.Forms Form Designer.
			InitializeComponent();
			UpdateTargetPosition = new MouseMoveHandler(Move2d);
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if( components != null )
					components.Dispose();
			}
			base.Dispose( disposing );
		}

		#region Component Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.Target = new System.Windows.Forms.Label();
			this.SuspendLayout();
			// 
			// Target
			// 
			this.Target.Font = new System.Drawing.Font("Microsoft Sans Serif", 20.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.Target.Location = new System.Drawing.Point(96, 96);
			this.Target.Name = "Target";
			this.Target.Size = new System.Drawing.Size(30, 30);
			this.Target.TabIndex = 0;
			this.Target.Text = "+";
			this.Target.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
			this.Target.DoubleClick += new System.EventHandler(this.SetZero);
			this.Target.MouseMove += new System.Windows.Forms.MouseEventHandler(this.MoveMousePos);
			this.Target.MouseDown += new System.Windows.Forms.MouseEventHandler(this.SetOffset);
			// 
			// MouseForm
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.BackColor = System.Drawing.SystemColors.AppWorkspace;
			this.ClientSize = new System.Drawing.Size(200, 200);
			this.ControlBox = false;
			this.Controls.Add(this.Target);
			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
			this.MaximizeBox = false;
			this.MinimizeBox = false;
			this.Name = "MouseForm";
			this.Opacity = 0.5;
			this.ShowInTaskbar = false;
			this.TopMost = true;
			this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.SetOffset);
			this.DoubleClick += new System.EventHandler(this.SetZero);
			this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.MoveMousePos);
			this.ResumeLayout(false);

		}
		#endregion

	}

}

